import collections
import time
import yaml
import os
import re
import json


# matches pattern like ${ENV_VAR} or ${ENV_VAR.SUB_ENV}
env_matcher = re.compile(r'\$\{(?P<name>[^{^}^.]+)(\.(?P<subname>[^{^}^.]+))?\}')


def sub_env(match_obj):
    env_name = match_obj.group('name')
    env_value = os.environ.get(env_name, '')
    env_subname = match_obj.group('subname')
    if env_subname:
        env_value = json.loads(env_value)
        env_value = env_value[env_subname]
    return env_value


def env_constructor(loader, node):
    value = loader.construct_scalar(node)
    return env_matcher.sub(sub_env, value)


class Config(collections.Mapping):
    default_expire = 300
    yaml_loader = yaml.FullLoader
    yaml_loader.add_implicit_resolver('!env', env_matcher, None)
    yaml_loader.add_constructor('!env', env_constructor)

    def __init__(self, config_path='w_config.yaml'):
        self.config_path = config_path

        self._data = None
        self._expire_time = int(time.time())

    @classmethod
    def set_default_expire(cls, expire):
        cls.default_expire = int(expire)

    @property
    def data(self):
        now = int(time.time())
        if (
            self._data is None or
            (
                self.default_expire and
                self._expire_time < now
            )
        ):
            self._data = self._load()
            self._expire_time = now + self.default_expire
        return self._data

    def _load(self):
        with open(self.config_path, 'r', encoding='utf-8') as f:
            return yaml.load(f, Loader=self.yaml_loader)

    def __getitem__(self, key):
        return self.data[key]

    def __len__(self):
        return len(self.data)

    def __iter__(self):
        return iter(self.data)


weather_config = Config()
